
// bind
Function.prototype.myBind = function(context) {
  if(typeof this !== 'function') {
    throw new Error('Type error')
  }
  let self = this
  let args = arguments.slice(1)
  return function(...arg) {
    self.apply(context, args.concat(arg))
  }
}

// call
Function.prototype.myCall = function(context) {
  if(typeof this !== 'function') {
    throw new Error('Type Error')
  }
  let res = null
  context = context || window
  let fnSymbol = Symbol()
  let args = [...arguments].slice(1)
  context[fnSymbol] = this
  res = context[fnSymbol](...args)
  delete context[fnSymbol]
  return res
}

// apply
Function.prototype.myApply = function(context) {
  if(typeof context !== 'function') {
    throw new Error('Type Error')
  }
  let res = null
  context = context || window
  let fnSymbol = Symbol()
  context[fnSymbol] = this
  if(arguments[1]) {
    res = context[fnSymbol](...arguments[1])
  } else {
    res = context[fnSymbol]()
  }
  delete context[fnSymbol]
  return res
}

// new
function myNew(context) {
  const obj = {}
  obj.__proto__ = context.prototype
  const res = context.apply(obj, [...arguments].slice(1))
  return typeof res === 'object' ? res : obj
}

// debounce
function debounce(fn, delay) {
  let timer = null
  let arg
  function debounced(...args) {
    arg = args
    if(timer) {
      clearTimeout(timer)
      timer = null
    }
    return new Promise((res, rej) => {
      try {
        timer = setTimeout(async () => {
          let result = await fn.apply(this, arg)
          res(result)
        }, delay)
      } catch(e) {
        rej(e)
      }
    })
  }
  function cancel() {
    clearTimeout(timer)
    timer = null
  }
  function flush() {
    cancel()
    return fn.apply(this, arg)
  }
  debounced.cancel = cancel
  debounced.flush = flush
  return debounced
}

function debounce2(fn, delay, immediate) {
  let timer
  return function(...args) {
    let context = this
    if(timer) clearTimeout(timer)
    if(immediate) {
      let canRun = !timer
      timer = setTimeout(() => {
        timer = null
      }, delay)
      if(canRun) {
        fn.apply(context, args)
      }
    } else {
      timer = setTimeout(() => {
        fn.apply(context, args)
      }, delay)
    }
  }
}


Promise.prototype.myAll = function(_promises) {
  const res = []
  const promises = Array.from(_promises);
  let count = 0
  return new Promise((resolve, reject) => {
    promises.forEach((promise, idx) => {
      Promise.resolve(promise).then((val) => {
        res[idx] = val
        if(++count == promises.length) {
          resolve(res)
        }
      }).catch((val) => reject(val))
    })
  })
}

Promise.prototype.myRace = function(_promises) {
  return new Promise((resolve, reject) => {
    _promises.forEach(item => {
      Promise.resolve(item)
      .then((val) => resolve(val))
      .catch(e => reject(e))
    })
  })
}
const obj = {}
this.chosenDataList.forEach((item, idx) => {
  obj[item.field] = this.infoData[idx]
})
console.log(obj)


XXX.records.map(item => {
  const obj = {}
  Object.entries(item.lineData).map(([key, val]) => {
    obj[key] = val.metaValue
  })
  return obj
})
 
function flatten(arr) {
  return arr.reduce((pre, cur) => {
    return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
  }, [])
}

function findMinAndMax(str) {
  const arr = str.split(',').map(Number)
  if(arr.length < 2) return 0
  let max = -Infinity, min = Infinity
  for(let i = 0; i < arr.length; i++) {
    if(arr[i] > max) max = arr[i]
    if(arr[i] < min) min = arr[i]
  }
  return max - min
}

function objToString(obj) {
  let str = ''
  for(let [key, val] of Object.entries(obj)) {
    str += `${key} is ${val}, `
  }
  return str.slice(0, -2)
}

function timeCalculator(time, add) {
  let date = new Date(`2023-03-02 ${time}`).getTime()
  let sum = 0
  add.forEach((item, idx) => {
    sum += item * 1000 * 60 ** (2 - idx)
  })
  return (new Date(date + sum)).toTimeString().slice(0, 8)
}